﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using log4net;
using NHibernate;
using NHibernate.Criterion;
using TeamCommunitySolution.Domain.DataLayer.TeamEvents;
using TeamCommunitySolution.Repositories.Providers;

namespace TeamCommunitySolution.Repositories.TeamEvents
{
    public class TeamEventRepositoryImpl : TeamEventRepository
    {
        /// <summary>
        /// The log instance.
        /// </summary>
        private static readonly ILog _log = LogManager.GetLogger(typeof(TeamEventRepository));

        private TeamEventRepositoryImpl()
        {
        }

        /// <summary>
        /// Creates the instance.
        /// </summary>
        /// <returns>Instance of the team event repository.</returns>
        public static TeamEventRepository CreateInstance()
        {
            return new TeamEventRepositoryImpl();
        }

        /// <summary>
        /// Saves the team event.
        /// </summary>
        /// <param name="teamEvent">The team event.</param>
        public void SaveTeamEvent(ref TeamEvent teamEvent)
        {
            using (ISession session = Nhibernate.Factory.OpenSession())
            {
                var scope = session.BeginTransaction();
                try
                {
                    teamEvent = (TeamEvent)session.SaveOrUpdateCopy(teamEvent);
                    scope.Commit();
                }
                catch (Exception ex)
                {
                    scope.Rollback();
                    string message = "Unable to save object [Team Event] in the datastore";
                    this.HandleException(message, ex);
                }
            }
        }

        /// <summary>
        /// Gets the team event by field.
        /// </summary>
        /// <param name="fieldName">The field name.</param>
        /// <param name="fieldValue">The field value.</param>
        /// <returns>Instance of the team event.</returns>
        public TeamEvent GetTeamEventByField(string fieldName, string fieldValue)
        {
            using (ISession session = Nhibernate.Factory.OpenSession())
            {
                ICriteria crit = session.CreateCriteria(typeof(TeamEvent));
                crit.Add(Expression.Eq(fieldName, fieldValue));

                IList<TeamEvent> results = crit.List<TeamEvent>();

                if (results.Count > 1)
                {
                    throw new TeamEventRepositoryException(string.Format("Duplicate objects [TeamEvent] found in the datastore. Field: {0}, Value: {1}", fieldName, fieldValue));
                }

                if (results.Count == 0)
                {
                    return null;
                }

                return results[0];
            }
        }

        /// <summary>
        /// Gets the team event invite by field.
        /// </summary>
        /// <param name="fieldName">Name of the field.</param>
        /// <param name="fieldValue">The field value.</param>
        /// <returns>Specified Team Invite</returns>
        public TeamEventInvite GetTeamEventInviteByField(string fieldName, string fieldValue)
        {
            using (ISession session = Nhibernate.Factory.OpenSession())
            {
                ICriteria crit = session.CreateCriteria(typeof(TeamEventInvite));
                crit.Add(Expression.Eq(fieldName, fieldValue));

                IList<TeamEventInvite> results = crit.List<TeamEventInvite>();

                if (results.Count > 1)
                {
                    throw new TeamEventRepositoryException(string.Format("Duplicate objects [TeamEventInvite] found in the datastore. Field: {0}, Value: {1}", fieldName, fieldValue));
                }

                if (results.Count == 0)
                {
                    return null;
                }

                return results[0];
            }
        }

        /// <summary>
        /// Saves the team event invite.
        /// </summary>
        /// <param name="invite">The invite.</param>
        public void SaveTeamEventInvite(TeamEventInvite invite)
        {
            using (ISession session = Nhibernate.Factory.OpenSession())
            {
                var scope = session.BeginTransaction();
                try
                {
                    session.SaveOrUpdate(invite);
                    scope.Commit();
                }
                catch (Exception ex)
                {
                    scope.Rollback();
                    string message = "Unable to save object [Team Event Invite] in the datastore";
                    this.HandleException(message, ex);
                }
            }
        }

        /// <summary>
        /// Handles the exception.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The exception.</param>
        private void HandleException(string message, Exception ex)
        {
            _log.Error(message, ex);
            throw new TeamEventRepositoryException(message, ex);
        }
    }
}
